import { JsonAsset, math } from "cc";
import { AssetLoadSync, AssetPath } from "../../../utils/assethelp";

export interface ThingConfig{
    Id: number, 
    Model: string,
    Typeb:number, 
    IsReq?:boolean
}

export interface ThingShowoutConfig {
    Cnt: number, 
    Thing: ThingConfig
}

export interface BoxConfig {
    tingid: number, 
    thingcnt: number
}

export interface LvBaseConfig{
    Id: string, 
    Title: string, 
    TypeLimit: number, 
    Scnt: string, 
    Tcnt:number, 
    UCnt: number
}

export interface LvRelConfig{
    Title: string, 
    Boxes: BoxConfig[], 
    Things: ThingShowoutConfig[]
}


export interface InGameConfig {
    lv?: Map<string, LvBaseConfig>
    thing?: Map<number, ThingConfig>
}




export class InGameModel{
    private _data:InGameConfig = {};
    clear() {
        this._data = {}
    }

    private updateData(key: string, conf : any){
        switch (key) {
            case "lv":
                this._data.lv = conf
                break;
            case "thing":
                this._data.thing = conf
                break
            default:
                break;
        }
    }

    private async getLvConfig(): Promise<JsonAsset>{
        let ret = await AssetLoadSync.loadRes<JsonAsset>(AssetPath.CONFIG.get("lv")||"")
        return ret
    }

    private async getThingConfig() : Promise<JsonAsset>{
        let ret = await AssetLoadSync.loadRes<JsonAsset>(AssetPath.CONFIG.get("thing")||"")
        return ret
    }

    private getThingsbyTypeb(typeb :number): Array<ThingConfig>{
        let tlist:Array<ThingConfig> = new Array<ThingConfig>()
        let all_thing:Map<number, ThingConfig> = this._data.thing!
        let thing
        for (const key of all_thing!) {
            thing = key[1]
            if (thing.Typeb == typeb || typeb == 0){
                tlist.push(thing)
            }
        }
        return tlist
    }
    
    private convert2RelConfig(baseconfig: LvBaseConfig):LvRelConfig {
        const thinglist = this.getThingsbyTypeb(baseconfig.TypeLimit)
        if (thinglist.length < baseconfig.Tcnt){
            console.error("Typeb <%d>dont't containe typel <%d>, fix the config!", baseconfig.TypeLimit, baseconfig.Tcnt)
        }
        let thingret:ThingShowoutConfig[] = [];
        let boxret: BoxConfig[]= [];

        /**根据配置生成必须的things */
        const times = baseconfig.Tcnt
        const scntarr = baseconfig.Scnt.split(",")
        let scnts, scnte
        for (let i = 0; i < times; i++) {
            const ran_thingidx = math.randomRangeInt(0, thinglist.length - 1)
            scnts = parseInt(scntarr[0])
            scnte = scntarr.length > 1?parseInt(scntarr[1]):scnts
            const ran_cnt = math.randomRangeInt(scnts, scnte)
            let tconf: ThingShowoutConfig = {
                Cnt:ran_cnt, 
                Thing:thinglist[ran_thingidx]
            }
            let bconf : BoxConfig = {
                thingcnt:ran_cnt, 
                tingid:tconf.Thing.Id
            }
            tconf.Thing.IsReq = true
            thinglist.splice(ran_thingidx, ran_thingidx)
            thingret.push(tconf)
            boxret.push(bconf)
        }

        /**随机加几个没用的 */
        // TODO
        
        /**顺带手生成box配置吧 */
        
        const ret:LvRelConfig = {
            Title:baseconfig.Title, 
            Things:thingret, 
            Boxes:boxret
        }
        return ret
    }
    
    public unpackLvConfig(conf: JsonAsset){
        let baseconf = conf.json
        let idarr, ids, ide
        let lvconf = new Map<String, LvBaseConfig>()
        for (const key in baseconf) {
            if (Object.prototype.hasOwnProperty.call(baseconf, key)) {
                const element = Reflect.get(baseconf, key)
                idarr = key.split(",")
                if (idarr.length != 2){
                    console.error("line <%s>'s id is not legal!", key)
                    break
                }
                ids = parseInt(idarr[0])
                ide = parseInt(idarr[1])
                for (let i = ids; i <= ide; i++) {
                    // lvconf()
                    lvconf.set(i.toString(), element)
                }
            }
        }
        return lvconf
    }

    public unpackThingConfig(conf: JsonAsset){
        let baseconf = conf.json
        let thingconf =  new Map<string, ThingConfig>()
        for (const key in baseconf) {
            if (Object.prototype.hasOwnProperty.call(baseconf, key)) {
                const element = Reflect.get(baseconf, key)
                thingconf.set(key, element)
            }
        }
        return thingconf
    }

    async updateConfig() : Promise<boolean>{
        this.clear()
        let errkey:string;
        let lv = await this.getLvConfig()
        let thing = await this.getThingConfig()
        return new Promise((resolve, _)=>{
            this.updateData("lv", this.unpackLvConfig(lv))  
            this.updateData("thing", this.unpackThingConfig(thing))    
            console.log("suc")      
            resolve(true)
        })  
    }

    get data(){
        return this._data
    }

    get thing() {
        return this._data.thing
    }
    
    public getConfigbyLvid(id: number) : LvRelConfig{
        const baseconfig = this._data.lv!.get(id.toString())
        const relconfig = this.convert2RelConfig(baseconfig!)
        return relconfig
    }
}
